package wesi.Table;

import java.awt.Component;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;

/**
 * Created by IntelliJ IDEA.
 * User: nastya.kuz
 * Date: 29.07.2010
 * Time: 17:29:02
 * Производиться управление структурой иерархии заголовков столбцов.
 * Имена столбцов могут быть одиночными, могут объединяться в группу, группы в свою очередь,
 * также могут быть объединены в группу более высокого уровня и т.д.
 */
public class ColumnGroup {

	private TableCellRenderer renderer;
	private ArrayList<ColumnGroup> groups;
	private ArrayList<TableColumn> columns;
	private String header;
	private int margin = 0;

	public ColumnGroup(String header) {
		this (null, header);
	}

	/**
	 * @param renderer    объект для отрисовывания ячейки таблицы
	 * @param headerValue значение заголовка столбца
	 */
	public ColumnGroup(TableCellRenderer renderer, String headerValue) {
		if (renderer == null) {
			this .renderer = new DefaultTableCellRenderer() {
				private static final long serialVersionUID = 1L;

				public Component getTableCellRendererComponent(
						JTable table, Object value, boolean isSelected,
						boolean hasFocus, int row, int column) {
					JTableHeader header = table.getTableHeader();
					if (header != null) {
						setForeground(header.getForeground());
						setBackground(header.getBackground());
						setFont(header.getFont());
					}
					setHorizontalAlignment(JLabel.CENTER);
					setText((value == null) ? "" : value.toString());
					setBorder(UIManager
							.getBorder("TableHeader.cellBorder"));
					return this ;
				}
			};
		} else {
			this .renderer = renderer;
		}
		this .header = headerValue;
		groups = new ArrayList<ColumnGroup>();
		columns = new ArrayList<TableColumn>();
	}

	/**
	 * Добавляет к списку столбцов
	 * столбец типа TableColumn
	 *
	 * @param column Добавляемый столбец
	 */
	public void add(TableColumn column) {
		if (column != null) {
			columns.add(column);
		}
	}

	/**
	 * Добавляет к списку групп
	 * группу столбцов типа ColumnGroup
	 *
	 * @param columnGroup Добавляемая группа
	 */
	public void add(ColumnGroup columnGroup) {
		if (columnGroup != null) {
			groups.add(columnGroup);
		}
	}

	/**
	 * определяет набор групп, к которым принадлежит столбец
	 *
	 * @param column      проверяемый столбец
	 * @param columnGroup при рекурсивном поиске хранит группу, в которой ищем
	 *
	 * @return набор групп, к которым принадлежит данный столбец
	 *         или null, если столбец не принадлежит ни одной группе
	 */
	public List<ColumnGroup> getColumnGroups(TableColumn column,
			List<ColumnGroup> columnGroup) {
		columnGroup.add(this );
		if (this .columns.contains(column)) {
			return columnGroup;
		}
		for (ColumnGroup group : groups) {
			ArrayList<ColumnGroup> listCopy = new ArrayList<ColumnGroup>(
					columnGroup);
			List<ColumnGroup> resultGroup = group.getColumnGroups(
					column, listCopy);
			if (resultGroup != null) {
				return resultGroup;
			}
		}
		return null;
	}

	public TableCellRenderer getHeaderRenderer() {
		return renderer;
	}

	public String getHeaderValue() {
		return header;
	}

	/**
	 * Определяет размеры таблицы table
	 *
	 * @param table Таблица
	 *
	 * @return размер таблицы
	 */
	public Dimension getSize(JTable table) {
		Component component = renderer.getTableCellRendererComponent(
				table, getHeaderValue(), false, false, -1, -1);
		int height = component.getPreferredSize().height;
		int width = 0;
		for (Object group : groups) {
			Dimension sizeTable = ((ColumnGroup) group).getSize(table);
			width += sizeTable.width;
		}
		for (TableColumn column : columns) {
			width += column.getWidth();
			width += margin;
		}
		return new Dimension(width, height);
	}

	/**
	 * устанавливает расстояние между ячейками столбца
	 *
	 * @param margin рассояние между ячейками столбца
	 */
	public void setColumnMargin(int margin) {
		this .margin = margin;
		for (ColumnGroup group : groups) {
			group.setColumnMargin(margin);
		}
	}
}
